package com.lkd.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.common.collect.Lists;
import com.lkd.dao.OrderCollectDao;
import com.lkd.entity.OrderCollectEntity;
import com.lkd.exception.LogicException;
import com.lkd.feign.UserService;
import com.lkd.service.OrderCollectService;
import com.lkd.vo.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.DayOfWeek;
import java.time.LocalDate;
import java.time.LocalDateTime;

import java.time.LocalTime;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;

@Service
@Slf4j
public class OrderCollectServiceImpl extends ServiceImpl<OrderCollectDao, OrderCollectEntity> implements OrderCollectService {
    @Autowired
    private UserService userService;

        @Override
        public List<OrderCollectEntity> getOwnerCollectByDate(Integer ownerId, LocalDate start, LocalDate end) {
            QueryWrapper<OrderCollectEntity> qw = new QueryWrapper<>();
            qw.lambda()
                    .eq(OrderCollectEntity::getOwnerId, ownerId)
                    .ge(OrderCollectEntity::getDate, start)
                    .le(OrderCollectEntity::getDate, end)
                    .groupBy(OrderCollectEntity::getNodeName, OrderCollectEntity::getDate)
                    .orderByDesc(OrderCollectEntity::getDate);

            return this.list(qw);
        }

    /**
     * 订单数统计
     * @param start
     * @param end
     * @return
     */

    /**
     * 订单数统计
     * 业务操作
     * 0、是否开启事务
     * 1、前端参数效验
     * 时间不为空
     * 日期前后时间逻辑正确
     * 2、关键参数效验
     * 3、业务操作
     * select count(*)
     * from tb_order_collect
     * where owner_id=1
     * and date Between "2022-12-13"
     * and "2022-12-14"
     * 4、返回结果
     * @param start 开始时间
     * @param end   结束时间
     * @return
     */
    @Override
    @Transactional
    public int orderCount(LocalDateTime start, LocalDateTime end) {

        //1、前端参数效验  2、关键参数效验
        //判断日期是否为空
        if (ObjectUtils.isEmpty(start) || ObjectUtils.isEmpty(end)) {
            throw new LogicException("查询的日期不能为空");
        }
        //判断时间是否有问题
        if (!(start.isBefore(end))) {
            throw new LogicException("end时间在start之前");
        }

        //3、业务操作
        var lw = new LambdaQueryWrapper<OrderCollectEntity>();
        //查询条件 ：开始时间  结束时间
        lw.between(OrderCollectEntity::getDate, start, end);
        //查询结果集合
        var count = this.count(lw);
        //4、返回结果
        return count;
    }

    /**
     *  业务分析
     *      1.判断关键数据
     *          前端传入的开始日期是否为空
     *          前端传入的结束日期是否为空
     *      2.判断业务数据
     *
     *      3.业务执行
     *          根据传入的开始结束的日期 查询数据表tb_order中的amount
     *      4.返回结果
     *          对返回结果的收集
     */

    /**
     * 本周订单数统计
     * 业务分析
     * 0、是否开启事务
     * 1、判断参数
     * 2、关键业务参数判断
     * 3、业务操作
     * 4、返回结果
     *
     * @param partnerId 合作商id
     * @param start     开始时间
     * @param end       结束时间
     * @return
     */
    @Override
    @Transactional
    public OrderCountResp orderCountInfo(Integer partnerId, LocalDateTime start, LocalDateTime end) {
        //1、前端参数效验  2、关键参数效验
        //合作商id不为空
        if (ObjectUtils.isEmpty(partnerId)) {
            throw new LogicException("合作商id不能为空");
        }
        //判断日期是否为空
        if (ObjectUtils.isEmpty(start) || ObjectUtils.isEmpty(end)) {
            throw new LogicException("查询的日期不能为空");
        }
        //判断时间是否有问题
        if (!(start.isBefore(end))) {
            throw new LogicException("end时间在start之前");
        }

        //  判断业务数据
        var wrapper1 = new LambdaQueryWrapper<OrderCollectEntity>();
        wrapper1.eq(OrderCollectEntity::getOwnerId, partnerId)
                .between(OrderCollectEntity::getDate, start, end);
        var count1 = this.count(wrapper1);
        // 获取上一个周的起始时间（周一的0:00）
        LocalDateTime startOfLastWeek = start.minusWeeks(1).with(DayOfWeek.MONDAY).with(LocalTime.MIN);
        // 获取上一个周的结束时间（周日的23:59:59）
        LocalDateTime endOfLastWeek = end.minusWeeks(1).with(DayOfWeek.SUNDAY).with(LocalTime.MAX);
        var wrapper2 = new LambdaQueryWrapper<OrderCollectEntity>();
        wrapper2.eq(OrderCollectEntity::getOwnerId, partnerId)
                .between(OrderCollectEntity::getDate, startOfLastWeek, endOfLastWeek);
        var count2 = this.count(wrapper2);
        Integer percent = 0;
        if (count2 < 1) {
            percent = count1 * 100 / 1;
        } else {
            percent = (count1 - count2) * 100 / count2;
        }
        //存放本周参数
        OrderCountResp orderCountResp = OrderCountResp.builder()
                .currentAmount(count1 + "")
                .percent(percent)
                .build();
        //返回结果
        return orderCountResp;
    }





    @Override
    public int orderAmount(LocalDateTime start, LocalDateTime end) {
        //  判断关键数据
        if (ObjectUtils.isEmpty(start) || ObjectUtils.isEmpty(end)) {
            throw new LogicException("参数信息不匹配");
        }
        return getCount(start, end);
        }
    public int getCount(LocalDateTime start,LocalDateTime end){
        QueryWrapper<OrderCollectEntity> queryWrapper = new QueryWrapper<>();
        queryWrapper.select("sum(order_total_money) as order_total_money")
                .lambda()
                .ge(OrderCollectEntity::getDate,start)
                .le(OrderCollectEntity::getDate,end);
        OrderCollectEntity or = this.getOne(queryWrapper);
        int orderTotalMoney = or.getOrderTotalMoney();
        return orderTotalMoney;
    }

    /**
     * 业务分析
     *     1.判断关键数据
     *          判断传入的开始/结束时间是否为空
     *     2.判断业务数据
     *
     *     3.业务执行
     *          根据传入的开始和结束日期 查询数据表tb_order_collect中的total——bill
     *     4.返回结果
     *          将得到的结果返回
     */

        @Override
        public int totalBill(LocalDateTime start, LocalDateTime end) {
            if(ObjectUtils.isEmpty(start)||ObjectUtils.isEmpty(end)){
                throw new LogicException("输入时间格式有问题");
            }
            return getCount1(start,end);

        }

    @Override
    public Pager<OrderCollectEntity> getPartnerCollect(Integer pageIndex, Integer pageSize, String name, LocalDate start, LocalDate end) {
        //判断关键数据
        if (ObjectUtils.isEmpty(pageIndex)){
            pageIndex=Pager.DEFAULT_PAGE_INDEX.intValue();
        }
        if (ObjectUtils.isEmpty(pageSize)){
            pageSize=Pager.DEFAULT_PAGE_SIZE.intValue();
        }
        if (ObjectUtils.isEmpty(start)
                ||ObjectUtils.isEmpty(end)){
            throw new LogicException("参数有误！！！");
        }
        //判断业务数据
        QueryWrapper<OrderCollectEntity> queryWrapper = new QueryWrapper<>();

        Page<OrderCollectEntity> orderPage = new Page<>(pageIndex, pageSize);
        if (!StringUtils.isEmpty(name)){
            queryWrapper.lambda().eq(OrderCollectEntity::getOwnerName,name)
                    .ge(OrderCollectEntity::getDate,start)
                    .le(OrderCollectEntity::getDate,end);
        }else {
            queryWrapper.lambda().ge(OrderCollectEntity::getDate,start)
                    .le(OrderCollectEntity::getDate,end);
        }
        Page<OrderCollectEntity> page = this.page(orderPage, queryWrapper);
        return  Pager.build(page);
    }


    public int getCount1(LocalDateTime start,LocalDateTime end){
        QueryWrapper<OrderCollectEntity> queryWrapper = new QueryWrapper<>();
        queryWrapper.select("sum(total_bill) as total_bill")
                .lambda()
                .ge(OrderCollectEntity::getDate,start)
                .le(OrderCollectEntity::getDate,end);
        OrderCollectEntity or = this.getOne(queryWrapper);
        int totalMoney = or.getTotalBill();
        return totalMoney;
    }




    /**
     * 获取合作商前12条点位分账数据
     * @param partnerId
     * @return
     */
    @Override
    public List<OrderCollectEntity> getTop12(Integer partnerId) {
        //  判断前端请求参数是否正确
        if (org.springframework.util.ObjectUtils.isEmpty(partnerId)) {
            throw new LogicException("请求参数不匹配");
        }
        //  判断业务数据
        PartnerVO partner = this.testPartnerByPartnerId(partnerId);
        //  业务操作
        /**
         * 获取合作商前12条点位分账数据
         *
         * @param partnerId
         * @return
         */
        var wrapper = new LambdaQueryWrapper<OrderCollectEntity>();
        wrapper.select(OrderCollectEntity::getNodeName, OrderCollectEntity::getTotalBill, OrderCollectEntity::getOrderCount, OrderCollectEntity::getDate)
                .eq(OrderCollectEntity::getOwnerId, partnerId).orderByDesc(OrderCollectEntity::getDate).last("limit 12");
        return this.list(wrapper);
    }

    /**
     * 合作商点位分账搜索
     * 业务分析
     * 0、是否开启事务
     * 1、判断前端请求参数是否正确
     * 合作商id不为空
     * 分页数据是否正确
     * 不正确给默认值
     * 2、判断业务关键参数是否存在
     * 合作商是否存在
     * 点位名称是否存在
     * 日期范围确认
     * 3、业务操作
     * 查询数据集合
     * 4、返回查询结果
     *
     * @param pageIndex 分页的第几页
     * @param pageSize  分页的每页数量
     * @param partnerId 合作商id
     * @param nodeName  点位名称
     * @param start     开始时间
     * @param end       结束时间
     * @return
     */
    @Override
    @Transactional
    public Pager<OrderCollectEntity> search(Long pageIndex, Long pageSize, Integer partnerId,
                                            String nodeName, LocalDate start, LocalDate end) {
        //1、判断前端请求参数是否正确
        //合作商id不为空
        if (ObjectUtils.isEmpty(partnerId)) {
            throw new LogicException("合作商id不能为空");
        }
        //判断日期是否为空
        if (ObjectUtils.isEmpty(start) || ObjectUtils.isEmpty(end)) {
            throw new LogicException("查询的日期不能为空");
        }
        //判断时间是否有问题
        if (!(start.isBefore(end))) {
            throw new LogicException("end时间在start之前");
        }
        //分页数据是否正确
        //分页页数
        if (pageIndex < 0 || pageIndex == null) {
            pageIndex = Pager.DEFAULT_PAGE_SIZE;
        }
        //分页内每页数据
        if (pageSize < 0 || pageSize == null) {
            pageSize = Pager.DEFAULT_PAGE_INDEX;
        }
        //2、判断业务关键参数是否存在
        //合作商是否存在
        PartnerVO partner = this.testPartnerByPartnerId(partnerId);
        if (ObjectUtils.isEmpty(partner)) {
            throw new LogicException("合作商不存在");
        }
        //创建分页查询对象
        Page<OrderCollectEntity> page = new Page<>(pageIndex, pageSize);
        //创建mq查询对象
        LambdaQueryWrapper<OrderCollectEntity> qw = new LambdaQueryWrapper<>();
        //3、业务操作
        //查询条件：合作商id
        qw.eq(OrderCollectEntity::getOwnerId, partnerId);
        //判断是否存在合作商名称 如果有加上这个查询条件
        if (!ObjectUtils.isEmpty(nodeName)) {
            qw.eq(OrderCollectEntity::getNodeName, nodeName);
        }
        //日期参数效验
        if (!ObjectUtils.isEmpty(start) && !ObjectUtils.isEmpty(end)) {
            qw
                    .ge(OrderCollectEntity::getDate, start)
                    .le(OrderCollectEntity::getDate, end);
        }
        //根据最后更新时间倒序排序
        qw.orderByDesc(OrderCollectEntity::getDate);

        //4、返回查询结果
        return Pager.build(this.page(page, qw));
    }


    /**
     * 获取一定日期内合作商的收益统计--》折线图
     * 业务分析
     * 0、是否要开启事务
     * 1、判断前端参数是否正确
     * 合作商id不为空
     * 日期不为空
     * 两个日期都为同一天 end结束时间向后推一天
     * 2、判断关键业务参数是否存在
     * 合作商是否存在
     * 3、业务操作
         * 查询参数集合
         * 4、返回结果
         * @param partnerId 合作商id
         * @param start     开始日期
         * @param end       结束日期
         * @return
         */
        @Override
        @Transactional
        public BarCharVO getCollect(Integer partnerId, LocalDate start, LocalDate end) {
            //1、判断前端请求参数是否正确
            //合作商id不为空
            if (ObjectUtils.isEmpty(partnerId)) {
                throw new LogicException("合作商id不能为空");
            }
            //判断日期是否为空
            if (ObjectUtils.isEmpty(start) || ObjectUtils.isEmpty(end)) {
                throw new LogicException("查询的日期不能为空");
            }
            //判断时间是否有问题
            if (!(start.isBefore(end))) {
                throw new LogicException("end时间在start之前");
            }

            //2、判断关键业务参数是否存在
            PartnerVO partner = this.testPartnerByPartnerId(partnerId);
            //3、业务操作
            //创建要返回的对象
            //X轴
            List<String> xAxis = Lists.newArrayList();
            //数据
            List<Integer> series = Lists.newArrayList();
            //创建查询对象
            LambdaQueryWrapper<OrderCollectEntity> lw = new LambdaQueryWrapper<>();
            //得到日期参数
            xAxis = this.getDate(start.toString(), end.toString());
            xAxis.stream().forEach(x -> series.add(0));
            //查询条件   合作商id  大于开始时间 小于结束时间
            //
            lw.eq(OrderCollectEntity::getOwnerId, partnerId)
                    .ge(OrderCollectEntity::getDate, start)
                    .le(OrderCollectEntity::getDate, end);
            //查询到日分成数据集合
            List<OrderCollectEntity> list = this.list(lw);
            List<String> finalXAxis = xAxis;
            //遍历覆盖
            list.stream().forEach(o -> {
                //通过时间判断得到对应的元素下标
                int index = finalXAxis.indexOf(o.getDate().toString());
                //得到原来数据
                int money=series.get(index);
                //总金额
                int totalBill=o.getTotalBill()+money;
                //覆盖
                series.set(index, totalBill);
            });
            //返回结果
            return BarCharVO.builder()
                    .xAxis(xAxis)
                    .series(series)
                    .build();
        }

    /**
     * 本周/月总收入情况
     * @param partnerId 合作商id
     * @param start     开始时间
     * @param end       结束时间
     * @return
     */
    @Override
    public TotalRevenueVo getTotalRevenue(Integer partnerId, LocalDateTime start, LocalDateTime end) {
        //  判断前端请求参数是否正确
        if (ObjectUtils.isEmpty(partnerId) || ObjectUtils.isEmpty(start) || ObjectUtils.isEmpty(end)) {
            throw new LogicException("请求参数不匹配");
        }
        //  判断业务数据
        if (ObjectUtils.isEmpty(userService.getPartner(partnerId))) {
            throw new LogicException("合作商不存在");
        }
        //  业务操作
        var wrapper = new LambdaQueryWrapper<OrderCollectEntity>();
        wrapper.eq(OrderCollectEntity::getOwnerId, partnerId).between(OrderCollectEntity::getDate, start, end);
        var list = this.list(wrapper);
        Integer price = list.stream().map(o -> o.getOrderTotalMoney() * o.getRatio()).reduce(0, (a, b) -> a + b);
        //  获取上一个周的起始时间（周一的0:00）
        LocalDateTime startOfLastWeek = start.minusWeeks(1).with(DayOfWeek.MONDAY).with(LocalTime.MIN);
        //  获取上一个周的结束时间（周日的23:59:59）
        LocalDateTime endOfLastWeek = end.minusWeeks(1).with(DayOfWeek.SUNDAY).with(LocalTime.MAX);
        wrapper.eq(OrderCollectEntity::getOwnerId, partnerId).between(OrderCollectEntity::getDate, startOfLastWeek, endOfLastWeek);
        var entityList = this.list(wrapper);
        Integer lastPrice = entityList.stream().map(o -> o.getOrderTotalMoney() * o.getRatio()).reduce(0, (a, b) -> a + b);
        //  获取同比
        int percent;
        if (lastPrice != 0) {
            percent = (price - lastPrice) / lastPrice;
        } else {
            percent = 0;
        }
        //  封装数据并返回
        TotalRevenueVo totalRevenueVo = new TotalRevenueVo();
        totalRevenueVo.setCurrentAmount(String.valueOf(price));
        totalRevenueVo.setPercent(Integer.valueOf(percent));
        return totalRevenueVo;
    }

    /**
     * 通过partnerId：合作商id判断合作商是否存在
     * @param partnerId 合作商id
     */
    private  PartnerVO testPartnerByPartnerId(Integer partnerId) {
        //合作商是否存在
        PartnerVO partner = userService.getPartner(partnerId);
        if (ObjectUtils.isEmpty(partner)) {
            throw new LogicException("合作商不存在");
        }
        return partner;
    }

    /**
     * 获取日期的集合
     *
     * @param startTime 开始时间
     * @param endTime   结束时间
     * @return
     */
    public List<String> getDate(String startTime, String endTime) {
        //定义时间格式
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
        List<String> list = new ArrayList<>();
        try {
            // 转化成日期类型
            Date startDate = simpleDateFormat.parse(startTime);
            Date endDate = simpleDateFormat.parse(endTime);

            //用Calendar 进行日期比较判断
            Calendar calendar = Calendar.getInstance();
            while (startDate.getTime() <= endDate.getTime()) {
                // 把日期添加到集合
                list.add(simpleDateFormat.format(startDate));
                // 设置日期
                calendar.setTime(startDate);
                //把日期增加一天
                calendar.add(Calendar.DATE, 1);
                // 获取增加后的日期
                startDate = calendar.getTime();
            }
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return list;
    }
}